#!/usr/bin/python

'''
Script para obtener los valores de moneda de las cotizaciones presentadas en 
determinada web, como por ejemplo la del Banco Republica (BROU) o 
Banco Central del Uruguay (BCU).

------------------------------------------------------------------------------

Documentacion sobre manejo de strings:

http://docs.python.org/library/re.html#re.MatchObject
http://docs.python.org/library/string.html
http://www.noah.org/wiki/RegEx_Python

S = re.search
S.group
'''

import urllib, re, psycopg2, sys, datetime


# -- BROU
try:
    BROU = "http://www.brou.com.uy/web/guest/institucional/cotizaciones"
    
    brou_htmlObj = urllib.urlopen(BROU)
    
    brou_html = brou_htmlObj.read()
    
    brou_html = brou_html.lower()
    
    brou_dolar = re.search(('\nd\xc3\xb3lar\n</td>\n<!-- no muestra buyvalue para' 
                            ' indice_down_jones -->\n<td class="buy">(\d+\.\d+)' 
                            '</td>\n<td class="sale">(\d+\.+\d+)'), brou_html)
    brou_dolarCompra = round(float(brou_dolar.group(1)), 2)
    brou_dolarVenta = round(float(brou_dolar.group(2)), 2)
    
    brou_euro = re.search(('euro\n</td>\n<!-- no muestra buyvalue para' 
                           ' indice_down_jones -->\n<td class="buy">(\d+\.\d+)' 
                           '</td>\n<td class="sale">(\d+\.+\d+)'), brou_html)
    brou_euroCompra = round(float(brou_euro.group(1)), 2)
    brou_euroVenta = round(float(brou_euro.group(2)), 2)
    
    
    # -- BCU
    BCU = "http://bcu.gub.uy/Paginas/Default.aspx"
    
    bcu_htmlObj = urllib.urlopen(BCU)
    
    bcu_html = bcu_htmlObj.read()
    
    bcu_html = bcu_html.lower()
    
    bcu_dolar = re.search('us\$ bill\r\n\s*</td>\r\n\s*<td.+>\r\n\s*(\d+.+\d+)', bcu_html)
    bcu_dolarValor = round(float(bcu_dolar.group(1).replace(',','.')), 3)
    
    bcu_euro = re.search('euro\r\n\s*</td>\r\n\s*<td.+>\r\n\s*(\d+.+\d+)', bcu_html)
    bcu_euroValor = round(float(bcu_euro.group(1).replace(',','.')), 3)
except:
    bcu_htmlObj = False

# Definir el string de conexion.
conn_string = ("host='localhost' port='5432' dbname='elremate'\
                user='remate' password='#r3m4t3'")

if not bcu_htmlObj:
    try:
        # Obtener una conexion; si no se conecta, 
        # una excepcion se genera aqui.
        conn = psycopg2.connect(conn_string)
        cursor = conn.cursor()
    except:
        # Obtener la excepcion mas reciente.
        exceptionType, exceptionValue, exceptionTraceback = sys.exc_info()
        sys.exit('\nHa fallado la conexion a la base de datos\n ->%s' % \
                    (exceptionValue))
        
    hoy = datetime.datetime.today()
    fecha = '%s-%s-%s' % (hoy.year, hoy.month, hoy.day)
    
    cursor.execute("SELECT compra FROM gestion_cotizaciones where moneda='USD' and fecha=(SELECT max(fecha) from gestion_cotizaciones)")  
    dolarCompra = cursor.fetchall()[0]  
    cursor.execute("SELECT venta FROM gestion_cotizaciones where moneda='USD' and fecha=(SELECT max(fecha) from gestion_cotizaciones)")  
    dolarVenta = cursor.fetchall()[0]
    cursor.execute("SELECT compra FROM gestion_cotizaciones where moneda='EUR' and fecha=(SELECT max(fecha) from gestion_cotizaciones)")  
    euroCompra = cursor.fetchall()[0]
    cursor.execute("SELECT venta FROM gestion_cotizaciones where moneda='EUR' and fecha=(SELECT max(fecha) from gestion_cotizaciones)")  
    euroVenta = cursor.fetchall()[0]
    cursor.execute("SELECT interbancario FROM gestion_cotizaciones where moneda='USD' and fecha=(SELECT max(fecha) from gestion_cotizaciones)")  
    dolarInter = cursor.fetchall()[0]
    cursor.execute("SELECT interbancario FROM gestion_cotizaciones where moneda='EUR' and fecha=(SELECT max(fecha) from gestion_cotizaciones)")  
    euroInter = cursor.fetchall()[0]
        
    # Inserta un nuevo registro si NO existe otro con esta fecha 
    # (repetir por cada moneda).
    cursor.execute(("INSERT INTO gestion_cotizaciones" 
                    " (fecha, moneda, compra, venta, interbancario)" 
                    " SELECT %s, 'USD', %s, %s, %s" 
                    " WHERE NOT EXISTS" 
                    " (SELECT fecha, moneda FROM gestion_cotizaciones" 
                    " WHERE fecha=%s AND moneda = 'USD')"), 
                   (fecha, dolarCompra, dolarVenta, dolarInter, fecha))
    cursor.execute(("INSERT INTO gestion_cotizaciones" + 
                    " (fecha, moneda, compra, venta, interbancario)" 
                    " SELECT %s, 'EUR', %s, %s, %s" 
                    " WHERE NOT EXISTS" 
                    " (SELECT fecha, moneda FROM gestion_cotizaciones" 
                    " WHERE fecha=%s AND moneda = 'EUR')"), 
                   (fecha, euroCompra, euroVenta, euroInter, fecha))

    # Actualiza el registro con esta fecha (repetir por cada moneda).
    cursor.execute(("UPDATE gestion_cotizaciones SET" 
                    " compra = %s, venta = %s, interbancario = %s" 
                    " WHERE fecha = %s AND moneda = 'USD'"), 
                   (dolarCompra, dolarVenta, dolarInter, fecha))
    cursor.execute(("UPDATE gestion_cotizaciones SET" 
                    " compra = %s, venta = %s, interbancario = %s" 
                    " WHERE fecha = %s AND moneda = 'EUR'"), 
                   (euroCompra, euroVenta, euroInter, fecha))

    conn.commit()
    cursor.close()
    conn.close()
    
    brou_dolarCompra=dolarCompra 
    brou_dolarVenta=dolarVenta 
    brou_euroCompra=euroCompra
    brou_euroVenta=euroVenta 
    bcu_dolarValor=dolarInter 
    bcu_euroValor=euroInter
    

# -- FUNCION PRINCIPAL
def insert_or_update(dolarCompra, dolarVenta, euroCompra, euroVenta, dolarInter,
                        euroInter, conn_string):
    '''Esta funcion toma los valores de las monedas por parametros\n
    dolarCompra, dolarVenta, euroCompra, euroVenta, dolarInter, \n
    euroInter y los inserta en la base de datos, usando el formato\n
    de fecha definido. Si el registro ya existe con la misma fecha\n
    en la base de datos, lo actualiza.'''

    hoy = datetime.datetime.today()
    fecha = '%s-%s-%s' % (hoy.year, hoy.month, hoy.day)
    
    print ("\n%s-%s-%s\t%s:%s:%s\n"
          "[ Dolar\tCompra: %s\tVenta: %s\t"
          "Interbancario: %s ] "
          "[ Euro\tCompra: %s\tVenta: %s\tInterbancario: %s ]") \
           % (
            hoy.day, 
            hoy.month, 
            hoy.year, 
            hoy.hour, 
            hoy.minute, 
            hoy.second,
            dolarCompra, 
            dolarVenta, 
            dolarInter, 
            euroCompra, 
            euroVenta, 
            euroInter
            ),
    
    try:
        # Obtener una conexion; si no se conecta, 
        # una excepcion se genera aqui.
        conn = psycopg2.connect(conn_string)
        cursor = conn.cursor()
        print 'Conectado!\t',
    except:
        # Obtener la excepcion mas reciente.
        exceptionType, exceptionValue, exceptionTraceback = sys.exc_info()
        sys.exit('\nHa fallado la conexion a la base de datos\n ->%s' % \
                    (exceptionValue))
    print 'Insertando datos...\t',

    # Inserta un nuevo registro si NO existe otro con esta fecha 
    # (repetir por cada moneda).
    cursor.execute(("INSERT INTO gestion_cotizaciones" 
                    " (fecha, moneda, compra, venta, interbancario)" 
                    " SELECT %s, 'USD', %s, %s, %s" 
                    " WHERE NOT EXISTS" 
                    " (SELECT fecha, moneda FROM gestion_cotizaciones" 
                    " WHERE fecha=%s AND moneda = 'USD')"), 
                   (fecha, dolarCompra, dolarVenta, dolarInter, fecha))
    cursor.execute(("INSERT INTO gestion_cotizaciones" + 
                    " (fecha, moneda, compra, venta, interbancario)" 
                    " SELECT %s, 'EUR', %s, %s, %s" 
                    " WHERE NOT EXISTS" 
                    " (SELECT fecha, moneda FROM gestion_cotizaciones" 
                    " WHERE fecha=%s AND moneda = 'EUR')"), 
                   (fecha, euroCompra, euroVenta, euroInter, fecha))

    # Actualiza el registro con esta fecha (repetir por cada moneda).
    cursor.execute(("UPDATE gestion_cotizaciones SET" 
                    " compra = %s, venta = %s, interbancario = %s" 
                    " WHERE fecha = %s AND moneda = 'USD'"), 
                   (dolarCompra, dolarVenta, dolarInter, fecha))
    cursor.execute(("UPDATE gestion_cotizaciones SET" 
                    " compra = %s, venta = %s, interbancario = %s" 
                    " WHERE fecha = %s AND moneda = 'EUR'"), 
                   (euroCompra, euroVenta, euroInter, fecha))

    conn.commit()
    cursor.close()
    conn.close()
    print "Finalizado.\n" + "-" * 50,

if __name__ == "__main__":
    insert_or_update(
                    brou_dolarCompra, 
                    brou_dolarVenta, 
                    brou_euroCompra, 
                    brou_euroVenta, 
                    bcu_dolarValor, 
                    bcu_euroValor,
                    conn_string
                    )
